/*
 * QE3e Qt Quick 3D Engine.
 * Copyright (C) 2010 Joris Vaillant and Mathieu Pujol 
 * <joris.vaillant@gmail.com>  <mathieu.pujol87@gmail.com>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <Material.h>

//Qt
#include <QDebug>

namespace qe3e
{
  MaterialPrivate::MaterialPrivate():
      mMode(Material::disable),
      mShininess(60),
      mAlphaRejectionValue(0.2f),
      mAlphaRejection(false),
      mBlending(true)
  {
    mAmbient[0]=0.2f;
    mAmbient[1]=0.2f;
    mAmbient[2]=0.2f;
    mAmbient[3]=1.f;
    mDiffuse[0]=0.9f;
    mDiffuse[1]=0.9f;
    mDiffuse[2]=0.9f;
    mDiffuse[3]=1.f;
    mSpecular[0]=1.f;
    mSpecular[1]=1.f;
    mSpecular[2]=1.f;
    mSpecular[3]=1.f;

  }

  Material::Material()
  {
    m_data = new MaterialPrivate();
  }


  void Material::setMode(mode colorMode)
  {
    m_data->mMode = colorMode;
  }

  Material::mode Material::getMode() const
  {
    return m_data->mMode;
  }

  void Material::setAmbient(const QColor & color)
  {
    m_data->mAmbient[0]=color.redF();
    m_data->mAmbient[1]=color.greenF();
    m_data->mAmbient[2]=color.blueF();
    // m_data->mAmbient[3]=color.alphaF();
  }

  void Material::setDiffuse(const QColor & color)
  {
    m_data->mDiffuse[0]=color.redF();
    m_data->mDiffuse[1]=color.greenF();
    m_data->mDiffuse[2]=color.blueF();
    //m_data->mDiffuse[3]=color.alphaF();
  }

  void Material::setSpecular(const QColor & color)
  {
    m_data->mSpecular[0]=color.redF();
    m_data->mSpecular[1]=color.greenF();
    m_data->mSpecular[2]=color.blueF();
    //m_data->mSpecular[3]=color.alphaF();
  }

  void Material::setAlpha(float alpha)
  {
    if(alpha<0.f)
      alpha=0.;
    if(alpha>1.f)
      alpha=1.;
    m_data->mAmbient[3]=alpha;
    m_data->mDiffuse[3]=alpha;
    m_data->mSpecular[3]=alpha;
  }

  void Material::setShininess(int s)
  {
    if(s >= 0 && s<= 128)
      m_data->mShininess = s;
  }

  int Material::getShininess() const
  {
    return m_data->mShininess;
  }

  void Material::setAlphaRejection(bool enable)
  {
    m_data->mAlphaRejection = enable;
  }

  void Material::setBlending(bool enable)
  {
    m_data->mBlending=enable;
  }

  bool Material::isBlending() const
  {
    return m_data->mBlending;
  }

  bool Material::isAlphaRejection() const
  {
    return m_data->mAlphaRejection;
  }

  void Material::setAlphaRejection(float alphaRejection)
  {
    if(alphaRejection < 0.f)
      alphaRejection = 0.f;
    if(alphaRejection > 1.f)
      alphaRejection = 1.f;
    m_data->mAlphaRejectionValue=alphaRejection;
  }

  float Material::getAlphaRejection() const
  {
    return m_data->mAlphaRejectionValue;
  }

  void Material::activateColorMaterial() const
  {

    if(m_data->mMode != disable)
    {
      glEnable(GL_COLOR_MATERIAL);
      switch(m_data->mMode)
      {
      case emission:
        glColorMaterial(GL_FRONT_AND_BACK,GL_EMISSION);
        break;
      case diffuse:
        glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
        break;
      case specular:
        glColorMaterial(GL_FRONT_AND_BACK,GL_SPECULAR);
        break;
      case ambiant:
        glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT);
        break;
      case ambiantAndDiffuse:
        glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
        break;
      default:
        glDisable(GL_COLOR_MATERIAL);
        break;
      }
      glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
    }

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_data->mAmbient);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_data->mDiffuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_data->mSpecular);
    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,m_data->mShininess);

  }

  void Material::releaseColorMaterial() const
  {
    glDisable(GL_COLOR_MATERIAL);
  }

  void Material::activateBlending() const
  {
    if(m_data->mBlending)
    {
      glEnable(GL_BLEND);
      /** @todo */
      //glBlendFunc(GL_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    }
  }

  void Material::releaseBlending() const
  {
    glDisable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ZERO);
  }

  void Material::addTexture(Texture & texture)
  {
    m_data->mTextures<<texture;
  }

  const QList<Texture> & Material::getTexture() const
  {
    return m_data->mTextures;
  }
}


